package com.cmpe.group6.storyroad;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.MultiAutoCompleteTextView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Toast;

import com.cmpe.group6.storyroad.jsonClasses.FreebaseResponse;
import com.cmpe.group6.storyroad.jsonClasses.ServerResponseObject;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.gson.Gson;

/**Activity that initializes the story creation process.
 * @author alicang
 *
 */
public class CreateStory extends Activity {

	RelativeLayout allowedUsers;

	private CreateStoryTask createStoryTask;

	private Activity currentActivity;
	private String parentId;

	private String storyTitle;
	private String storyBody;
	private String locationDescription;
	private String locationCoordinates;
	private String privileges;
	private boolean isPublic;
	private String allowUsers;
	private String tags;

	private ArrayList<String> tagHolder;
	private ArrayAdapter<String> tagAdapter;
	private ArrayList<AutoCompleteTextView> tagViews;

	private EditText storyTitleView;
	private EditText storyBodyView;
	private EditText locationView;
	private MultiAutoCompleteTextView allowedUsersView;
	private AutoCompleteTextView tagView;
	private RadioGroup privilegeView;
	private LinearLayout tagLayout;

	private GoogleMap map;
	private Marker marker;

	private ScrollView mainScrollView;
	
	/* (non-Javadoc)
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_create_story);
		currentActivity = this;
		final ActionBar bar = getActionBar();
		bar.setDisplayShowTitleEnabled(false);
		mainScrollView = (ScrollView) findViewById(R.id.scrollview);
		ImageView transparentImageView = (ImageView) findViewById(R.id.transparent_image);
		tagViews = new ArrayList<AutoCompleteTextView>();
		tagViews.add(tagView);
		privileges = "public";
		parentId = getIntent().getStringExtra("story_id");

		// Makes using google map smoother.
		transparentImageView.setOnTouchListener(new View.OnTouchListener() {

			/* (non-Javadoc)
			 * @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
			 */
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				int action = event.getAction();
				switch (action) {
				case MotionEvent.ACTION_DOWN:
					// Disallow ScrollView to intercept touch events.
					mainScrollView.requestDisallowInterceptTouchEvent(true);
					// Disable touch on transparent view
					return false;

				case MotionEvent.ACTION_UP:
					// Allow ScrollView to intercept touch events.
					mainScrollView.requestDisallowInterceptTouchEvent(false);
					return true;

				case MotionEvent.ACTION_MOVE:
					mainScrollView.requestDisallowInterceptTouchEvent(true);
					return false;

				default:
					return true;
				}
			}
		});

		map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
				.getMap();
		map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {

			// Adds marker if long click gesture is done on map.
			@Override
			public void onMapLongClick(LatLng arg0) {
				if (marker != null) {
					marker.remove();
				}
				marker = map.addMarker(new MarkerOptions()
						.position(new LatLng(arg0.latitude, arg0.longitude))
						.draggable(true).visible(true));
				locationCoordinates = marker.getPosition().toString();
			}
		});

		privilegeView = (RadioGroup) findViewById(R.id.privileges_radio);
		privilegeView.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			// If public option is checked, no need to show allowed users field.
			/* (non-Javadoc)
			 * @see android.widget.RadioGroup.OnCheckedChangeListener#onCheckedChanged(android.widget.RadioGroup, int)
			 */
			@Override
			public void onCheckedChanged(RadioGroup group, int checkedId) {
				if (checkedId == R.id.user_public) {
					privileges = "public";
					allowedUsers.setVisibility(View.GONE);
					isPublic = true;
				} else {
					privileges = "private";
					allowedUsers.setVisibility(View.VISIBLE);
					isPublic = false;

				}
			}
		});

		map.setMyLocationEnabled(true);
		tagView = (AutoCompleteTextView) findViewById(R.id.tag_selector_1);
		// Each character input recalls freebase for autocomplete list.
		tagView.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}

			@Override
			public void afterTextChanged(Editable s) {

				new FreebaseTask().execute(s.toString(), tagView);

			}
		});

		allowedUsers = (RelativeLayout) findViewById(R.id.allowed_users_container);
		RadioButton privateButton = (RadioButton) findViewById(R.id.user_private);
		storyTitleView = (EditText) findViewById(R.id.story_title);
		storyBodyView = (EditText) findViewById(R.id.story_body);
		locationView = (EditText) findViewById(R.id.location_description);
		allowedUsersView = (MultiAutoCompleteTextView) findViewById(R.id.allowed_user1);
		tagLayout = (LinearLayout) findViewById(R.id.tagholder);
		Button addTagButton = (Button) findViewById(R.id.add_tag);
		
		ArrayAdapter<String> userAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_dropdown_item_1line, Utils.users);

		allowedUsersView.setAdapter(userAdapter);
		allowedUsersView
				.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
		
		// Dynamically adding tag field.
		addTagButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				final AutoCompleteTextView textView = new AutoCompleteTextView(
						currentActivity);
				final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
						RelativeLayout.LayoutParams.FILL_PARENT,
						RelativeLayout.LayoutParams.WRAP_CONTENT);

				params.addRule(RelativeLayout.BELOW, R.id.tagholder);
				textView.setLayoutParams(params);
				textView.setId(tagView.getId() + 1);
				tagLayout.addView(textView, params);
				tagViews.add(textView);
				textView.addTextChangedListener(new TextWatcher() {

					@Override
					public void onTextChanged(CharSequence s, int start,
							int before, int count) {
					}

					@Override
					public void beforeTextChanged(CharSequence s, int start,
							int count, int after) {
					}

					// Freebase autocomplete for new tag fields.
					@Override
					public void afterTextChanged(Editable s) {

						new FreebaseTask().execute(s.toString(), textView);

					}
				});
			}
		});

		// Finalizing creating story with input checks.
		findViewById(R.id.finish_story).setOnClickListener(
				new OnClickListener() {

					@Override
					public void onClick(View v) {

						boolean isValid = true;
						
						//Checking if the title is empty.
						createStoryTask = new CreateStoryTask();
						storyTitle = storyTitleView.getText().toString();
						if (storyTitle.length() == 0) {
							storyTitleView.setError("Title cannot be empty");
							storyTitleView.requestFocus();
							isValid = false;
						}
						
						//Checking if the body is empty.
						storyBody = storyBodyView.getText().toString();
						if (storyBody.length() == 0) {
							storyBodyView
									.setError("Story Body cannot be empty");
							storyBodyView.requestFocus();
							isValid = false;
						}
						
						//Checking if the location description is empty.
						locationDescription = locationView.getText().toString();
						if (locationDescription.length() == 0) {
							locationView
									.setError("Location Description cannot be empty");
							locationView.requestFocus();
							isValid = false;
						}
						
						//Checking if user placed a marker for the location.
						if (marker == null) {
							Toast.makeText(getApplicationContext(),
									"Select a location using map!",
									Toast.LENGTH_SHORT).show();
							isValid = false;
						}

						tags = tagView.getText().toString();
						for (int i = 1; i < tagViews.size(); i++) {
							tags += "," + tagViews.get(i).getText().toString();
						}
						//Checking if user entered any tag.
						if (tags.length() == 0) {
							Toast.makeText(getApplicationContext(),
									"Please add at least one tag.",
									Toast.LENGTH_SHORT).show();
							isValid = false;
						}
						
						//If the must fields are filled, create story task is called.
						if (isValid) {
							allowUsers = allowedUsersView.getText().toString();
							locationCoordinates = locationCoordinates.replace(
									"lat/lng: (", "");
							locationCoordinates = locationCoordinates.replace(
									")", "");
							createStoryTask.execute((Void) null);
						}
					}
				});
	}
	
	/*
	 * (non-Javadoc)
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	/* Activating the top bar.
	 * (non-Javadoc)
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.home_button:
			Intent mainIntent = new Intent(this, MainActivity.class);
			startActivity(mainIntent);
			return true;
		case R.id.recommendations_button:
			Intent recomIntent = new Intent(this, RecommendationsActivity.class);
			startActivity(recomIntent);
			return true;
		case R.id.profile_button:
			Intent profileIntent = new Intent(this, ProfileActivity.class);
			startActivity(profileIntent);
			return true;
		case R.id.search_button:
			Intent searchIntent = new Intent(this, SearchActivity.class);
			startActivity(searchIntent);
			return true;
		case R.id.following_button:
			Intent followIntent = new Intent(this, FollowingActivity.class);
			startActivity(followIntent);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	/**
	 * Represents an asynchronous Create Story task to send the created story to
	 * server.
	 * 
	 */
	public class CreateStoryTask extends AsyncTask<Void, Void, Boolean> {
		@Override
		protected Boolean doInBackground(Void... params) {

			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(Utils.SERVER_NAME + "CreateStory");
			ServerResponseObject responseObject = new ServerResponseObject();

			try {
				// Add your data
				List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
				nameValuePairs.add(new BasicNameValuePair("username",
						Utils.username));
				nameValuePairs.add(new BasicNameValuePair("title", storyTitle));
				nameValuePairs.add(new BasicNameValuePair("body", storyBody));
				nameValuePairs.add(new BasicNameValuePair("location",
						locationDescription));
				nameValuePairs.add(new BasicNameValuePair("request_type",
						"Android"));
				nameValuePairs.add(new BasicNameValuePair("coordinates",
						locationCoordinates));
				nameValuePairs.add(new BasicNameValuePair("linking_option",
						privileges));
				if (!isPublic) {
					nameValuePairs.add(new BasicNameValuePair("allowed_list",
							allowUsers));
				}
				nameValuePairs.add(new BasicNameValuePair("tags", tags));
				if (parentId != null) {
					nameValuePairs.add(new BasicNameValuePair("parent_id",
							parentId));
				}
				// marker.getPosition
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,
						"UTF-8"));

				// Execute HTTP Post Request
				HttpResponse response = httpclient.execute(httppost);

				String jsonResponse = EntityUtils
						.toString(response.getEntity());
				Gson gson = new Gson();
				responseObject = gson.fromJson(jsonResponse,
						ServerResponseObject.class);

			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
			} catch (IOException e) {
				// TODO Auto-generated catch block
			}

			if (responseObject.isSuccess()) {
				return true;
			} else {
				return false;
			}
		}
		
		/*
		 * (non-Javadoc)
		 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
		 */
		@Override
		protected void onPostExecute(final Boolean success) {
			createStoryTask = null;

			if (success) {
				Toast.makeText(getApplicationContext(),
						"Story Creation Successful!", Toast.LENGTH_SHORT)
						.show();
				Intent mainActivityIntent = new Intent(currentActivity,
						MainActivity.class);
				startActivity(mainActivityIntent);

			}
		}

		@Override
		protected void onCancelled() {
			createStoryTask = null;
		}
	}

	/**
	 * Represents an asynchronous Freebase task to sending request to Freebase
	 * to get autocomplete list using the string input entered by the user.
	 * @param Object The input entered by the user.
	 */
	public class FreebaseTask extends AsyncTask<Object, Void, Boolean> {
		@Override
		protected Boolean doInBackground(Object... params) {
			String query = params[0].toString();
			final AutoCompleteTextView tw = (AutoCompleteTextView) params[1];
			HttpClient httpclient = new DefaultHttpClient();
			// JSONParser parser = new JSONParser();
			List<NameValuePair> parameters = new ArrayList<NameValuePair>();
			parameters.add(new BasicNameValuePair("query", query));
			parameters.add(new BasicNameValuePair("key", Utils.GOOGLE_API_KEY));

			String serviceURL = "https://www.googleapis.com/freebase/v1/search";
			String url = serviceURL + "?"
					+ URLEncodedUtils.format(parameters, "UTF-8");
			HttpResponse httpResponse = null;
			try {
				httpResponse = httpclient.execute(new HttpGet(url));
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			String response = "";
			try {
				response = EntityUtils.toString(httpResponse.getEntity());
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			Gson gson = new Gson();
			FreebaseResponse responseObject;
			responseObject = gson.fromJson(response, FreebaseResponse.class);
			tagHolder = new ArrayList<String>();
			for (int i = 0; i < responseObject.getResult().length; i++) {
				if (responseObject.getResult()[i].getNotable() != null) {
					tagHolder.add(responseObject.getResult()[i].getName()
							+ " ["
							+ responseObject.getResult()[i].getNotable()
									.getName() + "]");
				} else {
					tagHolder.add(responseObject.getResult()[i].getName());
				}
			}
			runOnUiThread(new Runnable() {
				public void run() {
					tagAdapter = new ArrayAdapter<String>(
							getApplicationContext(), R.layout.spinner_item,
							tagHolder);
					tw.setAdapter(tagAdapter);
					tagAdapter.notifyDataSetChanged();
				}
			});

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {

		}

		@Override
		protected void onCancelled() {

		}
	}

}
